package net.itxxw.manage_course.service;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sun.jmx.snmp.Timestamp;
import net.itxxw.framework.domain.cms.CmsPage;
import net.itxxw.framework.domain.cms.response.CmsPageResult;
import net.itxxw.framework.domain.cms.response.CmsPostPageResult;
import net.itxxw.framework.domain.course.*;
import net.itxxw.framework.domain.course.ext.CategoryNode;
import net.itxxw.framework.domain.course.ext.CourseInfo;
import net.itxxw.framework.domain.course.ext.CourseView;
import net.itxxw.framework.domain.course.ext.TeachplanNode;
import net.itxxw.framework.domain.course.request.CourseListRequest;
import net.itxxw.framework.domain.course.response.AddCourseResult;
import net.itxxw.framework.domain.course.response.CourseCode;
import net.itxxw.framework.domain.course.response.CoursePublishResult;
import net.itxxw.framework.exception.ExceptionCast;
import net.itxxw.framework.model.response.*;
import net.itxxw.manage_course.client.CmsPageClient;
import net.itxxw.manage_course.dao.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;


/**
 * @author：ycpan
 * @date：Created in 2020/12/13 14:15
 * @description：课程计划的查询
 * @modified By：
 * @version: 1$
 */
@Service
public class CourseService {
    @Autowired
    TeachplanMapper teachplanMapper;
    @Autowired
    TeachplanRepository teachplanRepository;
    @Autowired
    CourseBaseRepository courseBaseRepository;
    @Autowired
    CourseMapper courseMapper;
    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    CourseMarketRepository courseMarketRepository;
    @Autowired
    CoursePicRepository coursePicRepository;

    @Autowired
    CmsPageClient cmsPageClient;
    @Autowired
    CoursePubRepository coursePubRepository;
    @Autowired
    TeachplanMediaRepository teachplanMediaRepository;
    @Autowired
    TeachplanMediaPubRepository teachplanMediaPubRepository;

    @Value("${course-publish.dataUrlPre}")
    private String publish_dataUrlPre;
    @Value("${course-publish.pagePhysicalPath}")
    private String publish_page_physicalpath;
    @Value("${course-publish.pageWebPath}")
    private String publish_page_webpath;
    @Value("${course-publish.siteId}")
    private String publish_siteId;
    @Value("${course-publish.templateId}")
    private String publish_templateId;
    @Value("${course-publish.previewUrl}")
    private String previewUrl;



    //添加课程计划
    @Transactional //操作mysql需要添加事务注解
    public ResponseResult addTeachplan(Teachplan teachplan) {
        if (teachplan==null||
                StringUtils.isEmpty(teachplan.getCourseid())||
                StringUtils.isEmpty(teachplan.getPname())){
            ExceptionCast.cast(CommonCode.INVALID_PARAM);
        }
        //课程id
        String courseid=teachplan.getCourseid();
        //页面传入的parentId
        String parentid = teachplan.getParentid();
        if (StringUtils.isEmpty(parentid)){
           //取出该课程的根节点
            parentid = this.getTeachplanRoot(courseid);
        }

        Optional<Teachplan> optional = teachplanRepository.findById(parentid);
        Teachplan parentNode  = optional.get();
         //父节点的级别
        String grade = parentNode.getGrade();
        //新节点
         Teachplan teachplanNew=new Teachplan();
        //将页面提交的teachplan信息拷贝到teachplanbNew对象中
          BeanUtils.copyProperties(teachplan,teachplanNew);
          teachplanNew.setParentid(parentid);
          teachplanNew.setCourseid(courseid);
          if(grade.equals("1")){
              teachplanNew.setGrade("2");//级别,根据父节点的级别来设置
          }else{
              teachplanNew.setGrade("3");//级别,根据父节点的级别来设置
          }

          teachplanRepository.save(teachplanNew);

        return  new ResponseResult(CommonCode.SUCCESS);
    }

    //查询课程的根节点，如果查询不到自动添加根节点
    private String getTeachplanRoot(String courseId){
        Optional<CourseBase> optional = courseBaseRepository.findById(courseId);
        if (!optional.isPresent()){
            return null;
        }
        //课程信息
        CourseBase courseBase = optional.get();

        //查询课程的根节点
        List<Teachplan> teachplanList = teachplanRepository.findByCourseidAndParentid(courseId, "0");
        if(teachplanList==null||teachplanList.size()<=0){
            //查询不到，要自动添加跟节点
            Teachplan teachplan=new Teachplan();
            teachplan.setParentid("0");
            teachplan.setGrade("1");
            teachplan.setPname(courseBase.getName());
            teachplan.setCourseid(courseId);
            teachplan.setStatus("0");
            teachplanRepository.save(teachplan);
            return teachplan.getId();
        }
        //返回根结点的id
        return teachplanList.get(0).getId();
    }

    /**
     * 分页查询课程信息
     */
//用PageHelper查询课程列表的分页数据,参数为：当前页码，每页显示条数,扩展参数
    public QueryResult<CourseInfo> findCourseList(int page, int size, CourseListRequest courseListRequest) {
        if (courseListRequest==null){
            //如果扩展参数为空，就new一个，免得后面取值出现报错
            courseListRequest = new CourseListRequest();
        }

        if (page < 0){
            //进来的页面，要是小于0，就是非法参数，默认查第一页
            //PageHelper，的分页起始为1，不是0
            page = 1;
        }
        if (size < 0){
            //进来的显示条数，要是小于0，就是非法参数，默认查5条
            size = 5;
        }
        //启动分页插件，并且设置页码和显示条数
        PageHelper.startPage(page,size);
        //执行写好的sql方法
        Page<CourseInfo> courseListPage = courseMapper.findCourseList(courseListRequest);
        //QueryResult<CourseInfo>组装这个返回的分页对象
        //得到分页的数据集合
        List<CourseInfo> courseInfoList = courseListPage.getResult();
        //数据总条数
        long total = courseListPage.getTotal();
        QueryResult<CourseInfo> queryResult = new QueryResult<>();
        queryResult.setTotal(total);
        queryResult.setList(courseInfoList);

        return queryResult;

    }


    /**
     * 分页查询指定公司下的课程信息
     */
    public QueryResponseResult findCourseListByCompany(String companyId ,int pageNum, int size, CourseListRequest courseListRequest){
        if(pageNum<=0){
            pageNum = 0;
        }
        if(size<=0){
            size = 20;
        }
        PageHelper.startPage(pageNum,size);  //设置分页参数

        //设置公司信息到查询条件内
        courseListRequest.setCompanyId(companyId);
        Page<CourseInfo> courseList = courseMapper.findCourseListByCompany(courseListRequest);
        QueryResult queryResult = new QueryResult();
        queryResult.setList(courseList.getResult());
        queryResult.setTotal(courseList.getTotal());
        return new QueryResponseResult(CommonCode.SUCCESS,queryResult);
    }


    //根据id查询课程基本信息
    public CourseBase findCourseBaseById(String courseId){
        //获取课程信息
        Optional<CourseBase> optionalCourseBase = courseBaseRepository.findById(courseId);
        if(!optionalCourseBase.isPresent()){
            //课程不存在抛出异常
            ExceptionCast.cast(CourseCode.COURSE_NOTEXIST);
            return null;
        }
        return optionalCourseBase.get();
    }

//查询课程分类的数据方法
    public CategoryNode findCategoryList(){
        CategoryNode categoryList=categoryMapper.findCategoryList();
        return categoryList;
    }

//新增课程基础信息
    @Transactional
    public  AddCourseResult addCourseBase(CourseBase courseBase){
        //课程状态默认为未发布
        courseBase.setStatus("202001");
        courseBaseRepository.save(courseBase);
        return new AddCourseResult(CommonCode.SUCCESS,courseBase.getId());
    }


    //单查课程的基础信息，需要回显
    public CourseBase findCourseById(String courseid){
        Optional<CourseBase> optional = courseBaseRepository.findById(courseid);
        //从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常（NullPointerException） —— 每个 Java 程序员都非常了解的异常。
        if(optional.isPresent()){//判断查询对象是否存在
            CourseBase courseBase = optional.get();
            return courseBase;
        }
        return null;
    }

    //修改课程基础信息的方法
    @Transactional
    public ResponseResult updateCourse(String id,CourseBase courseBase){
        CourseBase one = this.findCourseById(id);
        //如果有这个数据，执行更改
        if(one==null){
            //传进来的参数，查不到数据，数据非法
            ExceptionCast.cast(CommonCode.INVALID_PARAM);
        }
        //修改课程信息
        one.setName(courseBase.getName());
        one.setMt(courseBase.getMt());
        one.setSt(courseBase.getSt());
        one.setGrade(courseBase.getGrade());
        one.setStudymodel(courseBase.getStudymodel());
        one.setUsers(courseBase.getUsers());
        one.setDescription(courseBase.getDescription());
        CourseBase save = courseBaseRepository.save(one);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    //单查课程营销信息
    public CourseMarket findMarketById(String courseid){
        Optional<CourseMarket> optional = courseMarketRepository.findById(courseid);
        if(optional.isPresent()){
            CourseMarket courseMarket = optional.get();
            return courseMarket;
        }
        return null;
    }

    //课程营销修改
    public ResponseResult updateMarket(String id,CourseMarket courseMarket){
        CourseMarket one = this.findMarketById(id);
        if(one!=null){
            one.setCharge(courseMarket.getCharge());//课程收费规则
            one.setStartTime(courseMarket.getStartTime());//课程有效期，开始时间
            one.setEndTime(courseMarket.getEndTime());//课程有效期，结束时间
            one.setPrice(courseMarket.getPrice());
            one.setQq(courseMarket.getQq());
            one.setValid(courseMarket.getValid());//课程有效性
            courseMarketRepository.save(one);
        }else{
            //如果没有这个营销信息，就新增这个营销信息
            //先清空查出来的数据
            one =new CourseMarket();
            BeanUtils.copyProperties(courseMarket,one);
            one.setId(id);
            courseMarketRepository.save(one);
        }
        //返回成功的信息
        return new ResponseResult(CommonCode.SUCCESS);
    }

    //添加课程图片的方法
    @Transactional
    public ResponseResult addCoursePic(String courseId, String pic) {
        //先准备一个对象
        CoursePic coursePic = null;

        //先查，有没有这个课程的图片信息
        Optional<CoursePic> one = coursePicRepository.findById(courseId);
        //如果有数据,就把现有对象取出来
        if (one.isPresent()){
            coursePic = one.get();
        }
        //如果没有数据,就创建一个新对象，再赋值
        if (coursePic == null) {
            coursePic = new CoursePic();
        }
        //如果没有这个课程图片对象，要创建一个对象新增进去
        coursePic.setCourseid(courseId);
        coursePic.setPic(pic);
        //最后执行保存
        coursePicRepository.save(coursePic);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    //    查询课程图片的方法
    public CoursePic findCoursePic(String courseId) {
        Optional<CoursePic> one = coursePicRepository.findById(courseId);
        if (one.isPresent()){
            CoursePic coursePic = one.get();
            System.err.println(coursePic);
            return coursePic;
        }
        return null;
    }

    //删除图片的方法
    @Transactional
    public ResponseResult deleteCoursePic(String courseId) {
        Long size = coursePicRepository.deleteByCourseid(courseId);
        //如果影响的行数，大于0,表示删除成功
        if (size>0){
            return new ResponseResult(CommonCode.SUCCESS);
        }
        return new ResponseResult(CommonCode.FAIL);
    }

    //取得课程详情的模板数据信息
    public CourseView getCourseView(String id){
        //准备一个coureseView对象接收,通过无参构造，生成对象
        CourseView courseView = new CourseView();
        //查询课程详情基本信息
        Optional<CourseBase> optionalBase = courseBaseRepository.findById(id);
        if (optionalBase.isPresent()){
            CourseBase courseBase = optionalBase.get();
            courseView.setCourseBase(courseBase);
        }

        // 查询课程详情图片
        Optional<CoursePic> optionalPic = coursePicRepository.findById(id);
        if (optionalPic.isPresent()){
            CoursePic coursePic = optionalPic.get();
            courseView.setCoursePic(coursePic);
        }
        // 查询课程详情营销
        Optional<CourseMarket> optionalMarket = courseMarketRepository.findById(id);
        if (optionalMarket.isPresent()){
            CourseMarket courseMarket = optionalMarket.get();
            courseView.setCourseMarket(courseMarket);
        }

        // 查询课程计划
        TeachplanNode teachplan = teachplanMapper.selectList(id);
        if (teachplan != null){
            courseView.setTeachplanNode(teachplan);
        }
        return courseView;
    }

    //通过课程id,取课程预览的接口
    public CoursePublishResult preview(String id) {
        //查询课程基本信息
        CourseBase courseBaseById = this.findCourseById(id);
        //请求cms添加页面
        //准备cmsPage信息
        CmsPage cmsPage = new CmsPage();
        cmsPage.setSiteId(publish_siteId);//站点id
        cmsPage.setDataUrl(publish_dataUrlPre+id);//数据模型url+课程id  http://localhost:31200/course/courseview/+id
        cmsPage.setPageName(id+".html");//页面名称
        cmsPage.setPageAliase(courseBaseById.getName());//页面别名，就是课程名称
        cmsPage.setPagePhysicalPath(publish_page_physicalpath);//页面物理路径
        cmsPage.setPageWebPath(publish_page_webpath);//页面webpath
        cmsPage.setTemplateId(publish_templateId);//页面模板id

        //远程调用cms,执行新页面的添加
        CmsPageResult cmsPageResult = cmsPageClient.saveCmsPage(cmsPage);
        System.err.println(cmsPageResult.getCmsPage());
        if(!cmsPageResult.isSuccess()){
            //如果添加不成功，就返回不成功
            return new CoursePublishResult(CommonCode.FAIL,null);
        }
        //添加页面成功，就取页面的id
        CmsPage cmsPage1 = cmsPageResult.getCmsPage();
        String pageId = cmsPage1.getPageId();
        //拼装页面预览的url
        String url = previewUrl+pageId;
        //返回CoursePublishResult对象（当中包含了页面预览的url）
        return new CoursePublishResult(CommonCode.SUCCESS,url);
    }

    //课程一键发布,传进来的是课程id
    @Transactional
    public CoursePublishResult publish(String courseId) {
        //提前需要拼装，课程页面信息

        //拼装页面信息
        CmsPage cmsPage = setPageInfo(courseId);

        //远程调用cms,发布课程详细页面
        CmsPostPageResult cmsPostPageResult = cmsPageClient.postPageQuick(cmsPage);
        //得到一个路径和操作状态的代码，如果不成功，返回异常失败
        if (!cmsPostPageResult.isSuccess()){
            ExceptionCast.cast(CommonCode.FAIL);
        }
        //如果成功了，把课程的发布状态设置改为，已发布
        CourseBase courseBase = this.saveCoursePubState(courseId);

        //还有索引相关，。。。。后面会写
        //保存课程索引信息
        //先创建一个coursePub对象
        CoursePub coursePub=createCoursePub(courseId);

        //将coursePub对象保存到数据库
        saveCoursePub(courseId,coursePub);

        //保存课程计划媒资信息到待索引表
        saveTeachplanMediaPub(courseId);

        //把得到的url,返回
        String pageUrl = cmsPostPageResult.getPostUrl();
        return new CoursePublishResult(CommonCode.SUCCESS,pageUrl);

    }

    private CoursePub saveCoursePub(String id, CoursePub coursePub) {
        if(StringUtils.isEmpty(id)) {
            ExceptionCast.cast(CourseCode.COURSE_PUBLISH_COURSEIDISNULL);
        }

        //        先准备一个新的索引
        CoursePub coursePubNew = null;
        //先通过id,查询有没有这个索引
        Optional<CoursePub> optionalPub =coursePubRepository.findById(id);
        if (optionalPub.isPresent()){
            //有这个索引就取出来备用
            coursePubNew = optionalPub.get();
        }else {
            //如果没有这个索引，就创建一个新的索引对象
            coursePubNew = new CoursePub();
        }
      //得到索引对象后，执行覆盖索引的操作。穿进来的新的覆盖旧的或者新new的
       BeanUtils.copyProperties(coursePub,coursePubNew);
        //最后把课程的id,设置一下
        coursePubNew.setId(id);
        //设置时间戳,给logstach使用

        coursePubNew.setTimestamp(new Date());


        //发布时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        String formatDateStr = simpleDateFormat.format(new Date());
        coursePubNew.setPubTime(formatDateStr);

        //保存对象到数据库
        CoursePub save = coursePubRepository.save(coursePubNew);
        return save;
    }
    //创建coursePub对象
    //创建课程索引的方法，这张表构成：课程Base+课程营销+课程图片+课程计划
    private CoursePub createCoursePub(String courseId) {
        //先创建空索引对象，再拼接每张表的参数，注入把数据复制进去的时候，2个对象都不能为null。
        CoursePub coursePub=new CoursePub();
        coursePub.setId(courseId);

        //基础信息
        Optional<CourseBase> baseRepositoryById = courseBaseRepository.findById(courseId);
        if(baseRepositoryById.isPresent()){
            //将courseBase对象信息复制到coursePub
            CourseBase courseBase = baseRepositoryById.get();
            BeanUtils.copyProperties(courseBase,coursePub);
        }
        //查询课程图片
        Optional<CoursePic> picOptional = coursePicRepository.findById(courseId);
        if(picOptional.isPresent()){
            CoursePic coursePic = picOptional.get();
            BeanUtils.copyProperties(coursePic, coursePub);
        }

        //课程营销信息
        Optional<CourseMarket> marketOptional = courseMarketRepository.findById(courseId);
        if(marketOptional.isPresent()){
            CourseMarket courseMarket = marketOptional.get();
            BeanUtils.copyProperties(courseMarket, coursePub);
        }

        //课程计划信息,转json
        TeachplanNode teachplanNode = teachplanMapper.selectList(courseId);
        if(teachplanNode != null){
            String teachPlanJsonString = JSON.toJSONString(teachplanNode);
            coursePub.setTeachplan(teachPlanJsonString);
        }

        return coursePub;

    }

    //更改课程的发布状态
    private CourseBase saveCoursePubState(String courseid){

        //通过课程id,查询课程base
        CourseBase courseBase = this.findCourseById(courseid);
        //查询不到，会返回异常，不用管
        courseBase.setStatus("202002");//设置课程发布状态为已发布
        //设置完成，返回课程
        return courseBase;
    }

     //拼装页面信息
    private CmsPage setPageInfo(String courseId){
        //获取课程信息
        CourseBase courseBaseById = this.findCourseBaseById(courseId);

        //拼装页面基本信息
        CmsPage cmsPage = new CmsPage();
        cmsPage.setDataUrl(publish_dataUrlPre + courseId);
        cmsPage.setPagePhysicalPath(publish_page_physicalpath);
        cmsPage.setPageWebPath(publish_page_webpath);
        cmsPage.setSiteId(publish_siteId);
        cmsPage.setTemplateId(publish_templateId);
        cmsPage.setPageName(courseId + ".html");

        //页面别名
        cmsPage.setPageAliase(courseBaseById.getName());
        return cmsPage;
    }

    //保存课程计划媒资信息
    private void  saveTeachplanMediaPub(String courseId){
      //查询课程媒资信息
        List<TeachplanMedia> teachplanMediaList= teachplanMediaRepository.findByCourseId(courseId);
       //将课程计划媒资信息存储待索引表
       teachplanMediaPubRepository.deleteByCourseId(courseId);
       List<TeachplanMediaPub>  teachplanMediaPubList=new ArrayList<>();
        for (TeachplanMedia teachplanMedia:teachplanMediaList){
            TeachplanMediaPub teachplanMediaPub=new TeachplanMediaPub();
            //timestamp 目标对象忽略的字段
            BeanUtils.copyProperties(teachplanMedia,teachplanMediaPub,"timestamp");
            teachplanMediaPub.setTimestamp(new Date());
            teachplanMediaPubList.add(teachplanMediaPub);
        }

       teachplanMediaPubRepository.saveAll(teachplanMediaPubList);

    }

    private void testfun(){

        System.out.println("测试方法！！！");
       // return "ok";
    }

}
